package ru.chaykin.util;

import java.nio.FloatBuffer;

import ru.chaykin.primitives.Point;

public abstract class Region {
	
	private static final float EPS = 1e-5f;
	private static final short ONE_INTERSECTION_POINT = 1;
	private static final short CHUNKS_ARE_PARALLEL = 0;
	private static final short  NO_INTERSCTION = -1;
	private static final short  A1_BORDER_INTERSECTION = 2;
	
	
	/**
	 returns
	   1 if there is one intersection point "c"
	   0 if chunks ar on parallel lines
	  -1 if there are no intersection points
	   2 if a1 lies on [b1,b2]
	 */
	private static short checkIntersection(Point a1, Point a2, Point b1, Point b2) {
		short result;
		float d,da,db,ta,tb;
	    d = (a1.getx() - a2.getx()) * (b2.gety() - b1.gety()) - (a1.gety() - a2.gety()) * (b2.getx() - b1.getx());
	    da = (a1.getx() - b1.getx()) * (b2.gety() - b1.gety()) - (a1.gety() - b1.gety()) * (b2.getx() - b1.getx());
	    db = (a1.getx() - a2.getx()) * (a1.gety() - b1.gety()) - (a1.gety() - a2.gety()) * (a1.getx() - b1.getx());

	   if (Math.abs(d) < EPS)
		   result = CHUNKS_ARE_PARALLEL;
	   else {
		   ta = da / d;
		   tb = db / d;
		   if ((Math.abs(ta) < EPS) && ((0 <= tb) && (tb <= 1)))
			   result = A1_BORDER_INTERSECTION;
		   else
			   if ((0 <= ta) && ( 0 <= tb) && (tb <= 1)) {
				   //c = new Point(a1.getx() + ta * (a2.getx() - a1.getx()), a1.gety() + ta * (a2.gety() - a1.gety()));
				   result = ONE_INTERSECTION_POINT;
			   }
	           else 
	        	   result = NO_INTERSCTION;
	   }
	   return result;
	}
	
	/**
	 * { 0 - outside
	   1 - inside
	   2 - on border
	 }
	 * @param a
	 * @param plg
	 * @return
	 */
	public static boolean pointInRegion(Point a, FloatBuffer plg) {
		int i,k,i1,i2,r;
	    Point ax = new Point(a.getx() + 5, a.gety()) ;
   	    k = 0;
	    for (i = 3; i < plg.position(); i +=3) {
	     i1 = i; 
	     i2 = i+3; 
	     if (i2 >= plg.position()) 
	    	 i2 = 3;
	     r = checkIntersection(a,ax,new Point(plg.get(i1), plg.get(i1 + 1)), new Point(plg.get(i2), plg.get(i2 + 1)));
	     if (r == 2) {
	       return true;
	     }
	     if (r == 1)
	       k = 1 - k;
	    }
	   return k == 1;
	}

/*	public static boolean pointInRegion(FloatBuffer region, float x, float y) {
		boolean c = true;
		 
	    for (int i = 0, j = region.position() - 1 - 3; i < region.position(); j = i += 3) {
	        if (((region.get(i + 1) > y) != (region.get(j + 1) > y)) && 
	        		(x < (region.get(j) - region.get(i)) * (y - region.get(i + 1)) / (region.get(j + 1) - region.get(i + 1)) + region.get(i))) {
	            c = !c;
	        }
	    }
	    return c;
	}*/
}
